package br.com.cfccultura.admin.model.dao.mysql;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;

import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Repository;

import br.com.cfccultura.admin.model.dao.IFuncionarioDAO;
import br.com.cfccultura.admin.model.dao.exceptions.SenhaInvalidaException;
import br.com.cfccultura.admin.model.dao.exceptions.UsuarioInativoException;
import br.com.cfccultura.admin.model.dao.exceptions.UsuarioInvalidoException;
import br.com.cfccultura.admin.model.enums.Ativo;
import br.com.cfccultura.admin.model.enums.TipoFuncionario;
import br.com.cfccultura.admin.model.vo.Funcionario;
import br.com.cfccultura.admin.model.vo.PontoEletronico;

@Repository
public class FuncionarioDAO extends DAO implements IFuncionarioDAO {

	private static final Logger logger = Logger.getLogger("FuncionarioDAO");


	public List<Funcionario> consultar(Funcionario vo) {
		Object[] params = new Object[0];
		String sql = 
				"SELECT cd_funcionario, nm_funcionario, dc_login, dc_email, id_tipo_funcionario, vl_hora, id_ativo " +
				"FROM tb_funcionario " +
				"WHERE ";
		if(vo.getCodigo() != null && vo.getCodigo() > 0) {
			sql += "cd_funcionario = ? and ";
			params = new Object[]{vo.getCodigo()};
		} else if(vo.getNome() != null && !vo.getNome().equals("")) {
			sql += "nm_funcionario like '" + vo.getNome() + "%' and ";
		} else if(vo.getLogin() != null && !vo.getLogin().equals("")) {
			sql += "dc_login = '" + vo.getLogin() + "' and ";
		} else if(vo.getTipo() != null) {
			sql += "id_tipo_funcionario = " + vo.getTipo().getValue() + " and ";
		}
		sql += "id_ativo = 1 ORDER BY nm_funcionario, dc_login";
		List<Funcionario> lista = query(sql, params, new RowMapper<Funcionario>() {
			public Funcionario mapRow(ResultSet rs, int arg1) throws SQLException {
				Funcionario vo = new Funcionario();
				vo.setCodigo(rs.getInt("cd_funcionario"));
				vo.setNome(rs.getString("nm_funcionario"));
				vo.setLogin(rs.getString("dc_login"));
				vo.setEmail(rs.getString("dc_email"));
				vo.setTipo(TipoFuncionario.setValue(rs.getInt("id_tipo_funcionario")));
				vo.setValorHora(rs.getDouble("vl_hora"));
				vo.setAtivo(Ativo.setValue(rs.getInt("id_ativo")));
				return vo;
			}			
		});
		
		return lista;
	}

	public Funcionario login(Funcionario vo) {
		String sql = 
				"SELECT cd_funcionario, nm_funcionario, dc_login, dc_senha, dc_email, id_tipo_funcionario, id_ativo " +
				"FROM tb_funcionario " +
				"WHERE dc_login = ?";
		List<Funcionario> lista = query(sql, new Object[]{vo.getLogin()}, new RowMapper<Funcionario>() {
			public Funcionario mapRow(ResultSet rs, int arg1) throws SQLException {
				Funcionario vo = new Funcionario();
				vo.setCodigo(rs.getInt("cd_funcionario"));
				vo.setNome(rs.getString("nm_funcionario"));
				vo.setLogin(rs.getString("dc_login"));
				vo.setSenha(rs.getString("dc_senha"));
				vo.setEmail(rs.getString("dc_email"));
				vo.setTipo(TipoFuncionario.setValue(rs.getInt("id_tipo_funcionario")));
				vo.setAtivo(Ativo.setValue(rs.getInt("id_ativo")));
				return vo;
			}			
		});
		
		Funcionario usuario = null;
		if(lista.size() == 1) {
			usuario = lista.get(0);
		}		
		
		if(usuario == null) {
			logger.warning("Usuario Invalido : " + vo.getLogin());
			throw new UsuarioInvalidoException();
		} else if(!usuario.getSenha().equals(vo.getSenha())) {
			logger.warning("Senha Invalida : " + vo.getLogin() + " - " + vo.getSenha());
			throw new SenhaInvalidaException();
		} else if(usuario.getAtivo().equals(Ativo.NAO)) {
			throw new UsuarioInativoException();
		}
		
		return usuario;
	}
	
	@Override
	public void alterar(Funcionario vo) {
		String sql = "UPDATE tb_funcionario set dc_login = ?, nm_funcionario = ?, dc_email = ?, id_tipo_funcionario = ?, vl_hora = ? where cd_funcionario = ?";
		update(sql, new Object[] {vo.getLogin(), vo.getNome(), vo.getEmail(), vo.getTipo().getValue(), vo.getValorHora(), vo.getCodigo()});
		
	}
	
	@Override
	public void excluir(Integer id) {
		try {
			String sql = "DELETE FROM tb_funcionario where cd_funcionario = ?";
			update(sql, new Object[] {id});
		} catch(DataIntegrityViolationException e) {
			String sql = "UPDATE tb_funcionario set id_ativo = 0 where cd_funcionario = ?";
			update(sql, new Object[] {id});			
		}	
	}
	
	@Override
	public void incluir(Funcionario vo) {
		String sql = "INSERT INTO tb_funcionario(nm_funcionario, dc_login, dc_senha, dc_email, id_tipo_funcionario, vl_hora, id_ativo) values(?,?,?,?,?,?,?)";
		update(sql, new Object[] {vo.getNome(), vo.getLogin(), vo.getSenha(), vo.getEmail(), vo.getTipo().getValue(), vo.getValorHora(), 1});		
	}

	@Override
	public void entrada(PontoEletronico vo) {
		String sql = "INSERT INTO tb_ponto_eletronico(cd_funcionario, dc_ip_entrada, dt_entrada) values(?,?,NOW())";
		update(sql, new Object[] {vo.getFuncionario().getCodigo(), vo.getIpEntrada()});
	}

	@Override
	public void saida(PontoEletronico vo) {
		
		String sql = "UPDATE tb_ponto_eletronico set dc_ip_saida = ?, dt_saida = NOW() WHERE cd_ponto_eletronico = ?";
		update(sql, new Object[] {vo.getIpSaida(), vo.getCodigo()});
		
	}
	
	@Override
	public PontoEletronico consultaPontoAtual(Funcionario vo) {
		
		String sql = "Select cd_ponto_eletronico, dt_entrada, dt_saida, dc_ip_entrada, dc_ip_saida from tb_ponto_eletronico where cd_funcionario = ? and DATE(dt_entrada) = CURDATE()";
		List<PontoEletronico> lista = query(sql, new Object[]{vo.getCodigo()}, new RowMapper<PontoEletronico>() {
			@Override
			public PontoEletronico mapRow(ResultSet rs, int arg1) throws SQLException {
				PontoEletronico ponto = new PontoEletronico();
				ponto.setCodigo(rs.getInt("cd_ponto_eletronico"));
				ponto.setEntrada(rs.getTimestamp("dt_entrada"));
				ponto.setSaida(rs.getTimestamp("dt_saida"));
				ponto.setIpEntrada(rs.getString("dc_ip_entrada"));
				ponto.setIpSaida(rs.getString("dc_ip_saida"));
				return ponto;
			}			
		});
		
		if(lista.size() == 1) {
			return lista.get(0);
		} else if(lista.size() > 1) {
			throw new RuntimeException("Lista retornou mais de um ponto eletronico na mesma data para o usuario -> " + vo.getLogin());
		} else {
			return null;
		}
	}
	
	@Override
	public List<PontoEletronico> consultaPontoEletronico(PontoEletronico vo) {
		
		List<Object> params = new ArrayList<Object>();
		String sql = "Select ponto.cd_ponto_eletronico, ponto.cd_funcionario, funcionario.nm_funcionario, ponto.dt_entrada, ponto.dt_saida, ponto.dc_ip_entrada, ponto.dc_ip_saida from tb_ponto_eletronico ponto, tb_funcionario funcionario where ";
		sql += "ponto.cd_funcionario = ? and ";
		params.add(vo.getFuncionario().getCodigo());

		sql += "ponto.cd_funcionario = funcionario.cd_funcionario and " +
				"DATE(ponto.dt_entrada) between ? and ? order by funcionario.nm_funcionario, ponto.dt_entrada";
		params.add(vo.getEntrada());
		params.add(vo.getSaida());
		
		List<PontoEletronico> lista = query(sql, params.toArray(), new RowMapper<PontoEletronico>() {
			@Override
			public PontoEletronico mapRow(ResultSet rs, int arg1) throws SQLException {
				PontoEletronico ponto = new PontoEletronico();
				ponto.setCodigo(rs.getInt("ponto.cd_ponto_eletronico"));
				ponto.setEntrada(rs.getTimestamp("ponto.dt_entrada"));
				ponto.setSaida(rs.getTimestamp("ponto.dt_saida"));
				ponto.setIpEntrada(rs.getString("ponto.dc_ip_entrada"));
				ponto.setIpSaida(rs.getString("ponto.dc_ip_saida"));
				ponto.setFuncionario(new Funcionario());
				ponto.getFuncionario().setCodigo(rs.getInt("ponto.cd_funcionario"));
				ponto.getFuncionario().setNome(rs.getString("funcionario.nm_funcionario"));
				return ponto;
			}			
		});
		
		return lista;
	}
	
}
